package com.verlet.web.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.verlet.web.handle.FallbackHandle;
import com.verlet.web.service.MessageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.net.URI;
import java.util.HashMap;
import java.util.Map;

/**
 * Sentinel 限流
 *
 * @author verlet
 */
@Slf4j
@RestController
@RequestMapping("/rateLimit")
public class RateLimitController {

    private final RestTemplate restTemplate;

    public RateLimitController(@Qualifier("httpRestTemplate") RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    /**
     * 按资源名称限流，需要指定限流处理逻辑
     * SentinelResource注解
     *   value 资源名
     *   blockHandler 限流处理方法
     *   blockHandlerClass 限流处理类 注意对应的函数必需为 static 函数
     *   defaultFallback 同时配置fallback,此方法会失效
     *   fallback 发生Throwable执行的方法
     *   fallbackClass 发生Throwable执行类
     *   exceptionsToIgnore 忽略某些异常
     */
    @GetMapping("/byResource")
    @SentinelResource(value = "byResource", blockHandler = "handleException",
            fallback = "handleException", fallbackClass = {FallbackHandle.class}, exceptionsToIgnore = NullPointerException.class)
    public Map<String, Object> byResource() {
        String forObject = restTemplate.getForObject(URI.create("http://localhost:9071/nacos/"), String.class);
        log.info(forObject);
        HashMap<String, Object> result = new HashMap<>();
        result.put("code", 200);
        result.put("msg", "按资源名称限流");
        return result;
    }

    /**
     * 按url限流，有默认的限流处理逻辑
     */
    @GetMapping("/byUrl")
    public Map<String, Object> byUrl() {
        Map<String, Object> result = new HashMap<>();
        result.put("code", 200);
        result.put("msg", "按url限流");
        return result;
    }

    /**
     * 当前方法的参数返回值和参数要跟原方法一致
     * 可以允许在参数列表的最后加入一个参数BlockException,用来接收原方法中发生的异常
     */
    public Map<String, Object> handleException(BlockException exception) {
        exception.printStackTrace();
        Map<String, Object> result = new HashMap<>();
        result.put("code", 200);
        result.put("msg", "自定义限流信息");
        return result;
    }

    @Autowired
    private MessageService messageService;
    @GetMapping("/getMessage1")
    public String getMessage1() {
        return "getMessage1==>"+ messageService.message();
    }

    @GetMapping("/getMessage2")
    public String getMessage2() {
        return "getMessage2==>"+ messageService.message();
    }

}